<!DOCTYPE html>



  


<html class="theme-next pisces use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="cnsyear Java 分布式 程序员">





  <link rel="alternate" href="/atom.xml" title="CNSYEAR BLOG'S" type="application/atom+xml">






<meta name="description" content="I MISS YOU.">
<meta property="og:type" content="website">
<meta property="og:title" content="CNSYEAR BLOG&#39;S">
<meta property="og:url" content="https://cnsyear.com/page/4/index.html">
<meta property="og:site_name" content="CNSYEAR BLOG&#39;S">
<meta property="og:description" content="I MISS YOU.">
<meta property="og:locale" content="zh-Hans">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="CNSYEAR BLOG&#39;S">
<meta name="twitter:description" content="I MISS YOU.">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":true,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://cnsyear.com/page/4/">





  <title>CNSYEAR BLOG'S</title>
  








</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left 
  page-home">
    <div class="headband">
	
		<a href="https://github.com/cnsyear" target="_blank" class="github-corner" aria-label="Follow me on GitHub"><svg width="80" height="80" viewbox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"/><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"/><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"/></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
	
		
	</div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">CNSYEAR BLOG'S</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">心有猛虎，细嗅蔷薇</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br>
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            时间轴
          </a>
        </li>
      
        
        <li class="menu-item menu-item-friends">
          <a href="/friends/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-globe"></i> <br>
            
            朋友们
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br>
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocomplete="off" placeholder="搜索..." spellcheck="false" type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            
  <section id="posts" class="posts-expand">
    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://cnsyear.com/2019/06/25/Springboot集成redisson实现分布式锁/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="趙小傑~～">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/1.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="CNSYEAR BLOG'S">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/06/25/Springboot集成redisson实现分布式锁/" itemprop="url">Springboot集成redisson实现分布式锁</a></h1>
        

        <div class="post-meta">
		 
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-06-25T22:19:41+08:00">
                2019-06-25
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/SpringBoot/" itemprop="url" rel="index">
                    <span itemprop="name">SpringBoot</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h3 id="一、简介"><a href="#一、简介" class="headerlink" title="一、简介"></a>一、简介</h3><p><strong>Redisson</strong>是架设在redis基础上的一个Java驻内存数据网格（In-Memory Data Grid）。充分的利用了Redis键值数据库提供的一系列优势，基于Java实用工具包中常用接口，为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力，大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务，更进一步简化了分布式环境中程序相互之间的协作。</p>
<p>Github地址：<a href="https://github.com/redisson/redisson" target="_blank" rel="noopener">https://github.com/redisson/redisson</a></p>
<h3 id="二、如何使用"><a href="#二、如何使用" class="headerlink" title="二、如何使用"></a>二、如何使用</h3><ul>
<li><p>1.引入重要的两个依赖，一个是spring-boot-starter-data-redis，一个是redisson</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;spring-boot-starter-data-redis&lt;/artifactId&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;org.redisson&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;redisson&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;3.7.5&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>
</li>
<li><p>2.application.properties中的相关配置</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># Redis服务器地址（默认session使用）</span><br><span class="line">spring.redis.host=192.168.1.201</span><br><span class="line"># Redis服务器连接密码（默认为空）</span><br><span class="line">spring.redis.password=</span><br><span class="line"># Redis服务器连接端口</span><br><span class="line">spring.redis.port=6390</span><br></pre></td></tr></table></figure>
</li>
<li><p>3.定义一个Loker接口，用于分布式锁的一些操作</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line">package com.rxjy.common.redissonlock;</span><br><span class="line">import java.util.concurrent.TimeUnit;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * 锁接口</span><br><span class="line"> * @author jie.zhao</span><br><span class="line"> */</span><br><span class="line">public interface Locker &#123;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取锁，如果锁不可用，则当前线程处于休眠状态，直到获得锁为止。</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     */</span><br><span class="line">    void lock(String lockKey);</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 释放锁</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     */</span><br><span class="line">    void unlock(String lockKey);</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取锁,如果锁不可用，则当前线程处于休眠状态，直到获得锁为止。如果获取到锁后，执行结束后解锁或达到超时时间后会自动释放锁</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     * @param timeout</span><br><span class="line">     */</span><br><span class="line">    void lock(String lockKey, int timeout);</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取锁,如果锁不可用，则当前线程处于休眠状态，直到获得锁为止。如果获取到锁后，执行结束后解锁或达到超时时间后会自动释放锁</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     * @param unit</span><br><span class="line">     * @param timeout</span><br><span class="line">     */</span><br><span class="line">    void lock(String lockKey, TimeUnit unit, int timeout);</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 尝试获取锁，获取到立即返回true,未获取到立即返回false</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    boolean tryLock(String lockKey);</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 尝试获取锁，在等待时间内获取到锁则返回true,否则返回false,如果获取到锁，则要么执行完后程序释放锁，</span><br><span class="line">     * 要么在给定的超时时间leaseTime后释放锁</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     * @param waitTime</span><br><span class="line">     * @param leaseTime</span><br><span class="line">     * @param unit</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit)</span><br><span class="line">            throws InterruptedException;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 锁是否被任意一个线程锁持有</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    boolean isLocked(String lockKey);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>4.实现类RedissonLocker，实现Locker中的方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line">package com.rxjy.common.redissonlock;</span><br><span class="line"></span><br><span class="line">import java.util.concurrent.TimeUnit;</span><br><span class="line"></span><br><span class="line">import org.redisson.api.RLock;</span><br><span class="line">import org.redisson.api.RedissonClient;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * 基于Redisson的分布式锁</span><br><span class="line"> * @author jie.zhao</span><br><span class="line"> */</span><br><span class="line">public class RedissonLocker implements Locker &#123;</span><br><span class="line"></span><br><span class="line">    private RedissonClient redissonClient;</span><br><span class="line"></span><br><span class="line">    public RedissonLocker(RedissonClient redissonClient) &#123;</span><br><span class="line">        super();</span><br><span class="line">        this.redissonClient = redissonClient;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public void lock(String lockKey) &#123;</span><br><span class="line">        RLock lock = redissonClient.getLock(lockKey);</span><br><span class="line">        lock.lock();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public void unlock(String lockKey) &#123;</span><br><span class="line">        RLock lock = redissonClient.getLock(lockKey);</span><br><span class="line">        lock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public void lock(String lockKey, int leaseTime) &#123;</span><br><span class="line">        RLock lock = redissonClient.getLock(lockKey);</span><br><span class="line">        lock.lock(leaseTime, TimeUnit.SECONDS);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public void lock(String lockKey, TimeUnit unit, int timeout) &#123;</span><br><span class="line">        RLock lock = redissonClient.getLock(lockKey);</span><br><span class="line">        lock.lock(timeout, unit);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public void setRedissonClient(RedissonClient redissonClient) &#123;</span><br><span class="line">        this.redissonClient = redissonClient;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public boolean tryLock(String lockKey) &#123;</span><br><span class="line">        RLock lock = redissonClient.getLock(lockKey);</span><br><span class="line">        return lock.tryLock();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public boolean tryLock(String lockKey, long waitTime, long leaseTime,</span><br><span class="line">                           TimeUnit unit) throws InterruptedException &#123;</span><br><span class="line">        RLock lock = redissonClient.getLock(lockKey);</span><br><span class="line">        return lock.tryLock(waitTime, leaseTime, unit);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public boolean isLocked(String lockKey) &#123;</span><br><span class="line">        RLock lock = redissonClient.getLock(lockKey);</span><br><span class="line">        return lock.isLocked();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>5.工具类LockUtil</p>
</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre></td><td class="code"><pre><span class="line">package com.rxjy.common.redissonlock;</span><br><span class="line"></span><br><span class="line">import java.util.concurrent.TimeUnit;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * redis分布式锁工具类</span><br><span class="line"> * @author jie.zhao</span><br><span class="line"> */</span><br><span class="line">public final class LockUtil &#123;</span><br><span class="line"></span><br><span class="line">    private static Locker locker;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 设置工具类使用的locker</span><br><span class="line">     *</span><br><span class="line">     * @param locker</span><br><span class="line">     */</span><br><span class="line">    public static void setLocker(Locker locker) &#123;</span><br><span class="line">        LockUtil.locker = locker;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取锁</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     */</span><br><span class="line">    public static void lock(String lockKey) &#123;</span><br><span class="line">        locker.lock(lockKey);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 释放锁</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     */</span><br><span class="line">    public static void unlock(String lockKey) &#123;</span><br><span class="line">        locker.unlock(lockKey);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取锁，超时释放</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     * @param timeout</span><br><span class="line">     */</span><br><span class="line">    public static void lock(String lockKey, int timeout) &#123;</span><br><span class="line">        locker.lock(lockKey, timeout);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取锁，超时释放，指定时间单位</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     * @param unit</span><br><span class="line">     * @param timeout</span><br><span class="line">     */</span><br><span class="line">    public static void lock(String lockKey, TimeUnit unit, int timeout) &#123;</span><br><span class="line">        locker.lock(lockKey, unit, timeout);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 尝试获取锁，获取到立即返回true,获取失败立即返回false</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    public static boolean tryLock(String lockKey) &#123;</span><br><span class="line">        return locker.tryLock(lockKey);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 尝试获取锁，在给定的waitTime时间内尝试，获取到返回true,获取失败返回false,获取到后再给定的leaseTime时间超时释放</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     * @param waitTime</span><br><span class="line">     * @param leaseTime</span><br><span class="line">     * @param unit</span><br><span class="line">     * @return</span><br><span class="line">     * @throws InterruptedException</span><br><span class="line">     */</span><br><span class="line">    public static boolean tryLock(String lockKey, long waitTime, long leaseTime,</span><br><span class="line">                                  TimeUnit unit) throws InterruptedException &#123;</span><br><span class="line">        return locker.tryLock(lockKey, waitTime, leaseTime, unit);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 锁释放被任意一个线程持有</span><br><span class="line">     *</span><br><span class="line">     * @param lockKey</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    public static boolean isLocked(String lockKey) &#123;</span><br><span class="line">        return locker.isLocked(lockKey);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>5.redisson的配置类RedissonConfig</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br></pre></td><td class="code"><pre><span class="line">package com.rxjy.common.config;</span><br><span class="line"></span><br><span class="line">import java.io.IOException;</span><br><span class="line"></span><br><span class="line">import com.rxjy.common.redissonlock.LockUtil;</span><br><span class="line">import com.rxjy.common.redissonlock.RedissonLocker;</span><br><span class="line">import org.redisson.Redisson;</span><br><span class="line">import org.redisson.api.RedissonClient;</span><br><span class="line">import org.redisson.config.Config;</span><br><span class="line">import org.redisson.config.SingleServerConfig;</span><br><span class="line">import org.springframework.beans.factory.annotation.Value;</span><br><span class="line">import org.springframework.context.annotation.Bean;</span><br><span class="line">import org.springframework.context.annotation.Configuration;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">@Configuration</span><br><span class="line">public class RedissonConfig &#123;</span><br><span class="line"></span><br><span class="line">    @Value(&quot;$&#123;spring.redis.database&#125;&quot;)</span><br><span class="line">    private int database;</span><br><span class="line">    @Value(&quot;$&#123;spring.redis.host&#125;&quot;)</span><br><span class="line">    private String host;</span><br><span class="line">    @Value(&quot;$&#123;spring.redis.port&#125;&quot;)</span><br><span class="line">    private String port;</span><br><span class="line">    @Value(&quot;$&#123;spring.redis.password&#125;&quot;)</span><br><span class="line">    private String password;</span><br><span class="line">    @Value(&quot;$&#123;spring.redis.timeout&#125;&quot;)</span><br><span class="line">    private int timeout;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * RedissonClient,单机模式</span><br><span class="line">     *</span><br><span class="line">     * @return</span><br><span class="line">     * @throws IOException</span><br><span class="line">     */</span><br><span class="line">    @Bean(destroyMethod = &quot;shutdown&quot;)</span><br><span class="line">    public RedissonClient redisson() &#123;</span><br><span class="line">        Config config = new Config();</span><br><span class="line">        SingleServerConfig singleServerConfig = config.useSingleServer();</span><br><span class="line">        singleServerConfig.setAddress(&quot;redis://&quot; + host + &quot;:&quot; + port);</span><br><span class="line">        singleServerConfig.setTimeout(timeout);</span><br><span class="line">        singleServerConfig.setDatabase(database);</span><br><span class="line">        if (password != null &amp;&amp; !&quot;&quot;.equals(password)) &#123; //有密码</span><br><span class="line">            singleServerConfig.setPassword(password);</span><br><span class="line">        &#125;</span><br><span class="line">        return Redisson.create(config);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Bean</span><br><span class="line">    public RedissonLocker redissonLocker(RedissonClient redissonClient) &#123;</span><br><span class="line">        RedissonLocker locker = new RedissonLocker(redissonClient);</span><br><span class="line">        //设置LockUtil的锁处理对象</span><br><span class="line">        LockUtil.setLocker(locker);</span><br><span class="line">        return locker;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">测试</span><br><span class="line"></span><br><span class="line">package com.rxjy.modules.group.controller;</span><br><span class="line"></span><br><span class="line">import com.rxjy.common.redissonlock.LockUtil;</span><br><span class="line">import org.springframework.web.bind.annotation.GetMapping;</span><br><span class="line">import org.springframework.web.bind.annotation.RestController;</span><br><span class="line"></span><br><span class="line">@RestController</span><br><span class="line">public class RedissonLockTest &#123;</span><br><span class="line"></span><br><span class="line">    static final String KEY = &quot;LOCK_KEY&quot;;</span><br><span class="line"></span><br><span class="line">    @GetMapping(&quot;/test&quot;)</span><br><span class="line">    public Object test()&#123;</span><br><span class="line">        //加锁</span><br><span class="line">        LockUtil.lock(KEY);</span><br><span class="line">        try &#123;</span><br><span class="line">            //TODO 处理业务</span><br><span class="line">            System.out.println(&quot; 处理业务。。。&quot;);</span><br><span class="line">        &#125; catch (Exception e) &#123;</span><br><span class="line">            //异常处理</span><br><span class="line">        &#125;finally&#123;</span><br><span class="line">            //释放锁</span><br><span class="line">            LockUtil.unlock(KEY);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        return &quot;SUCCESS&quot;;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
          
        
      
    </div>
    
    
    

	<div>
		
	</div>
	<div>
		
	</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://cnsyear.com/2019/06/25/Springboot中RedisTemplate使用scan代替keys/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="趙小傑~～">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/1.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="CNSYEAR BLOG'S">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/06/25/Springboot中RedisTemplate使用scan代替keys/" itemprop="url">Springboot中RedisTemplate使用scan代替keys</a></h1>
        

        <div class="post-meta">
		 
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-06-25T22:16:51+08:00">
                2019-06-25
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/SpringBoot/" itemprop="url" rel="index">
                    <span itemprop="name">SpringBoot</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <blockquote>
<p>Springboot中RedisTemplate使用scan代替keys</p>
</blockquote>
<p>keys * 这个命令千万别在生产环境乱用。</p>
<p>特别是数据庞大的情况下。因为Keys会引发Redis锁，并且增加Redis的CPU占用。很多公司的运维都是禁止了这个命令的</p>
<p>当需要扫描key，匹配出自己需要的key时，可以使用 scan 命令</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">import java.io.IOException;</span><br><span class="line">import java.nio.charset.StandardCharsets;</span><br><span class="line">import java.util.ArrayList;</span><br><span class="line">import java.util.List;</span><br><span class="line">import java.util.function.Consumer;</span><br><span class="line"></span><br><span class="line">import org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line">import org.springframework.data.redis.connection.RedisConnection;</span><br><span class="line">import org.springframework.data.redis.core.Cursor;</span><br><span class="line">import org.springframework.data.redis.core.ScanOptions;</span><br><span class="line">import org.springframework.data.redis.core.StringRedisTemplate;</span><br><span class="line">import org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line">@Component</span><br><span class="line">public class RedisHelper &#123;</span><br><span class="line">	</span><br><span class="line">	@Autowired</span><br><span class="line">	private StringRedisTemplate stringRedisTemplate;</span><br><span class="line">	</span><br><span class="line">	/**</span><br><span class="line">	 * scan 实现</span><br><span class="line">	 * @param pattern	表达式</span><br><span class="line">	 * @param consumer	对迭代到的key进行操作</span><br><span class="line">	 */</span><br><span class="line">	public void scan(String pattern, Consumer&lt;byte[]&gt; consumer) &#123;</span><br><span class="line">		this.stringRedisTemplate.execute((RedisConnection connection) -&gt; &#123;</span><br><span class="line">			try (Cursor&lt;byte[]&gt; cursor = connection.scan(ScanOptions.scanOptions().count(Long.MAX_VALUE).match(pattern).build())) &#123;</span><br><span class="line">				cursor.forEachRemaining(consumer);</span><br><span class="line">				return null;</span><br><span class="line">			&#125; catch (IOException e) &#123;</span><br><span class="line">				e.printStackTrace();</span><br><span class="line">				throw new RuntimeException(e);</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	/**</span><br><span class="line">	 * 获取符合条件的key</span><br><span class="line">	 * @param pattern	表达式</span><br><span class="line">	 * @return</span><br><span class="line">	 */</span><br><span class="line">	public List&lt;String&gt; keys(String pattern) &#123;</span><br><span class="line">		List&lt;String&gt; keys = new ArrayList&lt;&gt;();</span><br><span class="line">		this.scan(pattern, item -&gt; &#123;</span><br><span class="line">			//符合条件的key</span><br><span class="line">			String key = new String(item,StandardCharsets.UTF_8);</span><br><span class="line">			keys.add(key);</span><br><span class="line">		&#125;);</span><br><span class="line">		return keys;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>参考链接：</p>
<ul>
<li><a href="https://segmentfault.com/a/1190000004454805" target="_blank" rel="noopener">https://segmentfault.com/a/1190000004454805</a></li>
<li><a href="https://javaweb.io/post/175" target="_blank" rel="noopener">https://javaweb.io/post/175</a></li>
<li><a href="https://www.jianshu.com/p/d9f0a547bd0e" target="_blank" rel="noopener">https://www.jianshu.com/p/d9f0a547bd0e</a></li>
<li><a href="https://www.liangzl.com/get-article-detail-12938.html" target="_blank" rel="noopener">https://www.liangzl.com/get-article-detail-12938.html</a></li>
<li><p><a href="https://www.cnblogs.com/shamo89/p/8732398.html" target="_blank" rel="noopener">https://www.cnblogs.com/shamo89/p/8732398.html</a></p>
</li>
<li><p>亲测有效 <a href="https://springboot.io/t/topic/36" target="_blank" rel="noopener">https://springboot.io/t/topic/36</a></p>
</li>
</ul>

          
        
      
    </div>
    
    
    

	<div>
		
	</div>
	<div>
		
	</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://cnsyear.com/2019/06/25/Windows下Mysql5.7忘记密码如何重置/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="趙小傑~～">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/1.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="CNSYEAR BLOG'S">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/06/25/Windows下Mysql5.7忘记密码如何重置/" itemprop="url">Windows下Mysql5.7忘记密码如何重置</a></h1>
        

        <div class="post-meta">
		 
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-06-25T21:54:09+08:00">
                2019-06-25
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Mysql/" itemprop="url" rel="index">
                    <span itemprop="name">Mysql</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <blockquote>
<p>操作步骤</p>
</blockquote>
<ul>
<li>1.停止mysql服务</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">net stop mysql</span><br></pre></td></tr></table></figure>
<ul>
<li>2.关闭mysql安全检查</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">mysqld --skip-grant-tables</span><br><span class="line"></span><br><span class="line">// 备注:执行完毕之后,此时如果不是处于等待状态, 而是命令已经结束, 则证明服务</span><br><span class="line">// 有问题.</span><br><span class="line">// 楼主在这耽搁了很久, 后来重启电脑从第一部从新操作解决问题.</span><br></pre></td></tr></table></figure>
<ul>
<li>3.依次执行下面命令,重置密码</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">mysql -u root</span><br><span class="line"></span><br><span class="line">// 备注:该命令结束后,会出现enter password, 直接回车. 如果回车后报错, </span><br><span class="line">// 提示需要密码, 则步骤2出现问题. 可能mysql服务非正常停止. 我是通过重启</span><br><span class="line">// 电脑解决</span><br><span class="line"></span><br><span class="line">use mysql;</span><br><span class="line"></span><br><span class="line">UPDATE user SET authentication_string=PASSWORD(&quot;root&quot;) WHERE User=&apos;root&apos;;</span><br><span class="line">// 5.7以上密码对应字段为authentication_string,而非password</span><br><span class="line"></span><br><span class="line">FLUSH PRIVILEGES;</span><br><span class="line"></span><br><span class="line">quit;</span><br></pre></td></tr></table></figure>

          
        
      
    </div>
    
    
    

	<div>
		
	</div>
	<div>
		
	</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://cnsyear.com/2019/06/25/Nginx安装成windows服务/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="趙小傑~～">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/1.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="CNSYEAR BLOG'S">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/06/25/Nginx安装成windows服务/" itemprop="url">Nginx安装成windows服务</a></h1>
        

        <div class="post-meta">
		 
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-06-25T21:54:09+08:00">
                2019-06-25
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Nginx/" itemprop="url" rel="index">
                    <span itemprop="name">Nginx</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <blockquote>
<p>Nginx安装成windows服务</p>
</blockquote>
<p>需要借助”Windows Service Wrapper”小工具，<a href="https://github.com/kohsuke/winsw" target="_blank" rel="noopener">点击项目地址</a> ,<a href="http://repo.jenkins-ci.org/releases/com/sun/winsw/winsw/1.18/winsw-1.18-bin.exe" target="_blank" rel="noopener">点击下载地址</a><br>下载该工具后，将其放在 Nginx安装目录下，并重命名为nginx-service.exe，创建配置文件nginx-service.xml（名字要和工具名一样），创建nginx-service.exe.config（为支持NET 4.0 runtime，默认只支持NET 2.0 runtime）</p>
<p>文件结构如下：</p>
<p><img src="https://zj820382480.gitee.io/youdaoyun/image/微信截图_20190625220301.png" alt="image"></p>
<ul>
<li>nginx-service.xml</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;service&gt;</span><br><span class="line">  &lt;id&gt;nginx&lt;/id&gt;</span><br><span class="line">  &lt;name&gt;Nginx Service&lt;/name&gt;</span><br><span class="line">  &lt;description&gt;High Performance Nginx Service&lt;/description&gt;</span><br><span class="line">  &lt;logpath&gt;D:\xampp\nginx\logs&lt;/logpath&gt;</span><br><span class="line">  &lt;log mode=&quot;roll-by-size&quot;&gt;</span><br><span class="line">    &lt;sizeThreshold&gt;10240&lt;/sizeThreshold&gt;</span><br><span class="line">    &lt;keepFiles&gt;8&lt;/keepFiles&gt;</span><br><span class="line">  &lt;/log&gt;</span><br><span class="line">  &lt;executable&gt;D:\xampp\nginx\nginx.exe&lt;/executable&gt;</span><br><span class="line">  &lt;startarguments&gt;-p D:\xampp\nginx&lt;/startarguments&gt;</span><br><span class="line">  &lt;stopexecutable&gt;D:\xampp\nginx\nginx.exe&lt;/stopexecutable&gt;</span><br><span class="line">  &lt;stoparguments&gt;-p D:\xampp\nginx -s stop&lt;/stoparguments&gt;</span><br><span class="line">&lt;/service&gt;</span><br></pre></td></tr></table></figure>
<ul>
<li>nginx-service.exe.config</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&lt;configuration&gt;</span><br><span class="line">  &lt;startup&gt;</span><br><span class="line">    &lt;supportedRuntime version=&quot;v2.0.50727&quot; /&gt;</span><br><span class="line">    &lt;supportedRuntime version=&quot;v4.0&quot; /&gt;</span><br><span class="line">  &lt;/startup&gt;</span><br><span class="line">  &lt;runtime&gt;</span><br><span class="line">    &lt;generatePublisherEvidence enabled=&quot;false&quot;/&gt; </span><br><span class="line">  &lt;/runtime&gt;</span><br><span class="line">&lt;/configuration&gt;</span><br></pre></td></tr></table></figure>
<ul>
<li>在cmd中运行如下命令安装windows服务</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">D:\xampp\nginx\nginx-service.exe install</span><br></pre></td></tr></table></figure>
<p>之后就可以在Windows服务面板中启动服务了<br><img src="https://zj820382480.gitee.io/youdaoyun/image/微信截图_20190625220445.png" alt="image"></p>
<p>参考链接：</p>
<ul>
<li><a href="https://blog.csdn.net/zflovecf/article/details/79622585" target="_blank" rel="noopener">https://blog.csdn.net/zflovecf/article/details/79622585</a></li>
</ul>

          
        
      
    </div>
    
    
    

	<div>
		
	</div>
	<div>
		
	</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://cnsyear.com/2019/06/02/Tomcat8配置tomcat-usersxml不生效/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="趙小傑~～">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/1.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="CNSYEAR BLOG'S">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/06/02/Tomcat8配置tomcat-usersxml不生效/" itemprop="url">Tomcat8配置tomcat-users.xml不生效</a></h1>
        

        <div class="post-meta">
		 
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-06-02T10:29:21+08:00">
                2019-06-02
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Tomcat/" itemprop="url" rel="index">
                    <span itemprop="name">Tomcat</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <blockquote>
<p>Tomcat8配置tomcat-users.xml不生效</p>
</blockquote>
<p>一般想进入tomcat管理后台，只要在tomcat-users.xml配置文件中添加一下内容即可 ,tomcat webapp  中必须保留 manager 项目</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;role rolename=&quot;admin-gui&quot;/&gt;</span><br><span class="line">&lt;role rolename=&quot;manager-gui&quot;/&gt;</span><br><span class="line">&lt;role rolename=&quot;manager-script&quot;/&gt;</span><br><span class="line">&lt;user username=&quot;manager&quot; password=&quot;manager&quot; roles=&quot;manager-gui,manager-script&quot;/&gt;</span><br><span class="line">&lt;user username=&quot;admin&quot; password=&quot;admin&quot; roles=&quot;admin-gui,manager-gui&quot;/&gt;</span><br></pre></td></tr></table></figure>
<p>但是今天下载了tomcat8.5，配置之后页面仍然显示403错误提示，这时仔细观察了一下403页面的英文，才发现如果在安装tomcat以外的机器进入tomcat后台，需要修改manager项目的配置文件。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/apache-tomcat-8.5.24/webapps/host-manager/META-INF</span><br><span class="line">发现有一个content.xml</span><br><span class="line"></span><br><span class="line">修改</span><br><span class="line"> &lt;Valve className=&quot;org.apache.catalina.valves.RemoteAddrValve&quot;</span><br><span class="line">       allow=&quot;127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1&quot; /&gt;</span><br><span class="line">为：</span><br><span class="line">&lt;Valve className=&quot;org.apache.catalina.valves.RemoteAddrValve&quot;</span><br><span class="line">         allow=&quot;\d+\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1&quot; /&gt;</span><br></pre></td></tr></table></figure>
<p>即可使用tomcat-users.xml中配置的用户进入tomcat的后台管理界面了。</p>

          
        
      
    </div>
    
    
    

	<div>
		
	</div>
	<div>
		
	</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://cnsyear.com/2019/06/01/通告/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="趙小傑~～">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/1.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="CNSYEAR BLOG'S">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/06/01/通告/" itemprop="url">网站升级通告</a></h1>
        

        <div class="post-meta">
		 
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-06-01T00:00:00+08:00">
                2019-06-01
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/通告/" itemprop="url" rel="index">
                    <span itemprop="name">通告</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <blockquote>
<p>网站升级通告</p>
</blockquote>
<p>为提升访问速度和SEO收录，本站于2019年6月全面升级到Coding中。<br>百度收录旧版文章链接失效正在处理中，如需查看请访问旧版<a href="https://cnsyear.github.io" target="_blank" rel="noopener">https://cnsyear.github.io</a> 。</p>
<p>升级内容：</p>
<ul>
<li><del>站点迁移到Coding 已完成</del></li>
<li>百度收录、谷歌收录</li>
<li>评论系统、<del>看板娘</del>、DaoVoice </li>
<li>Next版本升级到6.x或7.x <a href="https://kinegratii.github.io/2018/07/23/migrate-to-hexo-next-6/" target="_blank" rel="noopener">https://kinegratii.github.io/2018/07/23/migrate-to-hexo-next-6/</a></li>
</ul>

          
        
      
    </div>
    
    
    

	<div>
		
	</div>
	<div>
		
	</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://cnsyear.com/2019/03/24/心有猛虎，细嗅蔷薇/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="趙小傑~～">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/1.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="CNSYEAR BLOG'S">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/03/24/心有猛虎，细嗅蔷薇/" itemprop="url">心有猛虎，细嗅蔷薇</a></h1>
        

        <div class="post-meta">
		 
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-03-24T23:24:18+08:00">
                2019-03-24
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/句读/" itemprop="url" rel="index">
                    <span itemprop="name">句读</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <blockquote>
<p>心有猛虎，细嗅蔷薇</p>
</blockquote>
<p><img src="http://zj820382480.gitee.io/youdaoyun/image/ertyuikjhgfdg0.jpg" alt="image"></p>
<p>英国诗人西格里夫·萨松代表作《于我，过去，现在以及未来 》的经典诗句。原话是“In me the tiger sniffs the rose.”诗人 余光中将其翻译为：心有猛虎，细嗅蔷薇。意思是，老虎也会有细嗅蔷薇的时候， 忙碌而远大的雄心也会被温柔和美丽折服，安然感受美好。</p>

          
        
      
    </div>
    
    
    

	<div>
		
	</div>
	<div>
		
	</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://cnsyear.com/2019/03/24/Vue发请求需要传数组/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="趙小傑~～">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/1.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="CNSYEAR BLOG'S">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/03/24/Vue发请求需要传数组/" itemprop="url">Vue发请求需要传数组</a></h1>
        

        <div class="post-meta">
		 
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-03-24T19:50:00+08:00">
                2019-03-24
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/vue/" itemprop="url" rel="index">
                    <span itemprop="name">vue</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <ul>
<li>vue中用axios发请求，需要传一个数组，数组中是对对象，直接传的话，会默认调用string方法传入的是[object,object],然后用JSON.stringify方法转换了一下，还是不行，数组要怎样传啊？</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">let arr = [1,2,3]</span><br><span class="line">axios(&#123;url: &apos;/user/&apos;,</span><br><span class="line">    params: &#123;</span><br><span class="line">        id: arr + &apos;&apos;,    // 重点在这数组加上&apos;&apos;,即可变为 &quot;1,2,3&quot;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">所形成的url为： /user?id=1,2,3    等价于 /user?id=1&amp;id=2&amp;id=3</span><br></pre></td></tr></table></figure>

          
        
      
    </div>
    
    
    

	<div>
		
	</div>
	<div>
		
	</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://cnsyear.com/2019/03/24/Springboot之多任务并行-线程池处理/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="趙小傑~～">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/1.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="CNSYEAR BLOG'S">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/03/24/Springboot之多任务并行-线程池处理/" itemprop="url">Springboot之多任务并行+线程池处理</a></h1>
        

        <div class="post-meta">
		 
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-03-24T16:07:00+08:00">
                2019-03-24
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/SpringBoot/" itemprop="url" rel="index">
                    <span itemprop="name">SpringBoot</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <blockquote>
<p>springboot之多任务并行+线程池处理</p>
</blockquote>
<p>最近项目中做到一个关于批量发短信的业务，如果用户量特别大的话，不能使用单线程去发短信，只能尝试着使用多任务来完成</p>
<p><img src="https://zj820382480.gitee.io/youdaoyun/image/pasted-0.png" alt="image"></p>
<ul>
<li>Java 线程池</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Java通过Executors提供四种线程池，分别为：</span><br><span class="line"></span><br><span class="line">newCachedThreadPool创建一个可缓存线程池，如果线程池长度超过处理需要，可灵活回收空闲线程，若无可回收，则新建线程。</span><br><span class="line">newFixedThreadPool 创建一个定长线程池，可控制线程最大并发数，超出的线程会在队列中等待。</span><br><span class="line">newScheduledThreadPool 创建一个定长线程池，支持定时及周期性任务执行。</span><br><span class="line">newSingleThreadExecutor 创建一个单线程化的线程池，它只会用唯一的工作线程来执行任务，保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。</span><br><span class="line"></span><br><span class="line">优点</span><br><span class="line">重用存在的线程，减少对象创建、消亡的开销，性能佳。</span><br><span class="line">可有效控制最大并发线程数，提高系统资源的使用率，同时避免过多资源竞争，避免堵塞。</span><br><span class="line">提供定时执行、定期执行、单线程、并发数控制等功能。</span><br></pre></td></tr></table></figure>
<ul>
<li>方式一 CountDownLatch</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line">public class StatsDemo &#123;</span><br><span class="line">    final static SimpleDateFormat sdf = new SimpleDateFormat(</span><br><span class="line">            &quot;yyyy-MM-dd HH:mm:ss&quot;);</span><br><span class="line"></span><br><span class="line">    final static String startTime = sdf.format(new Date());</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * IO密集型任务  = 一般为2*CPU核心数（常出现于线程中：数据库数据交互、文件上传下载、网络数据传输等等）</span><br><span class="line">     * CPU密集型任务 = 一般为CPU核心数+1（常出现于线程中：复杂算法）</span><br><span class="line">     * 混合型任务  = 视机器配置和复杂度自测而定</span><br><span class="line">     */</span><br><span class="line">    private static int corePoolSize = Runtime.getRuntime().availableProcessors();</span><br><span class="line">    /**</span><br><span class="line">     * public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,</span><br><span class="line">     *                           TimeUnit unit,BlockingQueue&lt;Runnable&gt; workQueue)</span><br><span class="line">     * corePoolSize用于指定核心线程数量</span><br><span class="line">     * maximumPoolSize指定最大线程数</span><br><span class="line">     * keepAliveTime和TimeUnit指定线程空闲后的最大存活时间</span><br><span class="line">     * workQueue则是线程池的缓冲队列,还未执行的线程会在队列中等待</span><br><span class="line">     * 监控队列长度，确保队列有界</span><br><span class="line">     * 不当的线程池大小会使得处理速度变慢，稳定性下降，并且导致内存泄露。如果配置的线程过少，则队列会持续变大，消耗过多内存。</span><br><span class="line">     * 而过多的线程又会 由于频繁的上下文切换导致整个系统的速度变缓——殊途而同归。队列的长度至关重要，它必须得是有界的，这样如果线程池不堪重负了它可以暂时拒绝掉新的请求。</span><br><span class="line">     * ExecutorService 默认的实现是一个无界的 LinkedBlockingQueue。</span><br><span class="line">     */</span><br><span class="line">    private static ThreadPoolExecutor executor  = new ThreadPoolExecutor(corePoolSize, corePoolSize+1, 10l, TimeUnit.SECONDS,</span><br><span class="line">            new LinkedBlockingQueue&lt;Runnable&gt;(1000));</span><br><span class="line"></span><br><span class="line">    public static void main(String[] args) throws InterruptedException &#123;</span><br><span class="line">        CountDownLatch latch = new CountDownLatch(5);</span><br><span class="line">        //使用execute方法</span><br><span class="line">          executor.execute(new Stats(&quot;任务A&quot;, 1000, latch));</span><br><span class="line">          executor.execute(new Stats(&quot;任务B&quot;, 1000, latch));</span><br><span class="line">          executor.execute(new Stats(&quot;任务C&quot;, 1000, latch));</span><br><span class="line">          executor.execute(new Stats(&quot;任务D&quot;, 1000, latch));</span><br><span class="line">          executor.execute(new Stats(&quot;任务E&quot;, 1000, latch));</span><br><span class="line">        latch.await();// 等待所有人任务结束</span><br><span class="line">        System.out.println(&quot;所有的统计任务执行完成:&quot; + sdf.format(new Date()));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    static class Stats implements Runnable  &#123;</span><br><span class="line">        String statsName;</span><br><span class="line">        int runTime;</span><br><span class="line">        CountDownLatch latch;</span><br><span class="line"></span><br><span class="line">        public Stats(String statsName, int runTime, CountDownLatch latch) &#123;</span><br><span class="line">            this.statsName = statsName;</span><br><span class="line">            this.runTime = runTime;</span><br><span class="line">            this.latch = latch;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        public void run() &#123;</span><br><span class="line">            try &#123;</span><br><span class="line">                System.out.println(statsName+ &quot; do stats begin at &quot;+ startTime);</span><br><span class="line">                //模拟任务执行时间</span><br><span class="line">                Thread.sleep(runTime);</span><br><span class="line">                System.out.println(statsName + &quot; do stats complete at &quot;+ sdf.format(new Date()));</span><br><span class="line">                latch.countDown();//单次任务结束，计数器减一</span><br><span class="line">            &#125; catch (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>方式二 Future</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line">重点是和springboot整合，采用注解bean方式生成ThreadPoolTaskExecutor</span><br><span class="line"></span><br><span class="line">@Bean</span><br><span class="line"></span><br><span class="line">//spring依赖包</span><br><span class="line">import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;</span><br><span class="line">@Configuration</span><br><span class="line">public class GlobalConfig &#123;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 默认线程池线程池</span><br><span class="line">     *</span><br><span class="line">     * @return Executor</span><br><span class="line">     */</span><br><span class="line">    @Bean</span><br><span class="line">    public ThreadPoolTaskExecutor defaultThreadPool() &#123;</span><br><span class="line">        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();</span><br><span class="line">        //核心线程数目</span><br><span class="line">        executor.setCorePoolSize(16);</span><br><span class="line">        //指定最大线程数</span><br><span class="line">        executor.setMaxPoolSize(64);</span><br><span class="line">        //队列中最大的数目</span><br><span class="line">        executor.setQueueCapacity(16);</span><br><span class="line">        //线程名称前缀</span><br><span class="line">        executor.setThreadNamePrefix(&quot;defaultThreadPool_&quot;);</span><br><span class="line">        //rejection-policy：当pool已经达到max size的时候，如何处理新任务</span><br><span class="line">        //CALLER_RUNS：不在新线程中执行任务，而是由调用者所在的线程来执行</span><br><span class="line">        //对拒绝task的处理策略</span><br><span class="line">        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());</span><br><span class="line">        //线程空闲后的最大存活时间</span><br><span class="line">        executor.setKeepAliveSeconds(60);</span><br><span class="line">        //加载</span><br><span class="line">        executor.initialize();</span><br><span class="line">        return executor;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">使用</span><br><span class="line"></span><br><span class="line">//通过注解引入配置</span><br><span class="line">@Resource(name = &quot;defaultThreadPool&quot;)</span><br><span class="line">private ThreadPoolTaskExecutor executor;</span><br><span class="line"></span><br><span class="line">    //使用Future方式执行多任务</span><br><span class="line">    //生成一个集合</span><br><span class="line">    List&lt;Future&gt; futures = new ArrayList&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    //获取后台全部有效运营人员的集合</span><br><span class="line">    List&lt;AdminUserMsgResponse&gt; adminUserDOList = adminManagerService.GetUserToSentMsg(null);</span><br><span class="line"></span><br><span class="line">    for (AdminUserMsgResponse response : adminUserDOList) &#123;</span><br><span class="line">        //并发处理</span><br><span class="line">        if (response.getMobile() != null) &#123;</span><br><span class="line">            Future&lt;?&gt; future = executor.submit(() -&gt; &#123;</span><br><span class="line">                //发送短信</span><br><span class="line">                mobileMessageFacade.sendCustomerMessage(response.getMobile(), msgConfigById.getContent());</span><br><span class="line">            &#125;);</span><br><span class="line">            futures.add(future);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">  //查询任务执行的结果</span><br><span class="line">   for (Future&lt;?&gt; future : futureList) &#123;</span><br><span class="line">        while (true) &#123;//CPU高速轮询：每个future都并发轮循，判断完成状态然后获取结果，这一行，是本实现方案的精髓所在。即有10个future在高速轮询，完成一个future的获取结果，就关闭一个轮询</span><br><span class="line"> if (future.isDone()&amp;&amp; !future.isCancelled()) &#123;//获取future成功完成状态，如果想要限制每个任务的超时时间，取消本行的状态判断+future.get(1000*1, TimeUnit.MILLISECONDS)+catch超时异常使用即可。</span><br><span class="line">     Integer i = future.get();//获取结果</span><br><span class="line">    System.out.println(&quot;任务i=&quot;+i+&quot;获取完成!&quot;+new Date());</span><br><span class="line">    list.add(i);</span><br><span class="line">    break;//当前future获取结果完毕，跳出while</span><br><span class="line">&#125; else &#123;</span><br><span class="line">    Thread.sleep(1);//每次轮询休息1毫秒（CPU纳秒级），避免CPU高速轮循耗空CPU---》新手别忘记这个</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>参考链接：</p>
<ul>
<li><a href="https://blog.csdn.net/qq_31673689/article/details/80311235" target="_blank" rel="noopener">https://blog.csdn.net/qq_31673689/article/details/80311235</a></li>
</ul>

          
        
      
    </div>
    
    
    

	<div>
		
	</div>
	<div>
		
	</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://cnsyear.com/2019/03/24/Springboot多线程并发定时任务/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="趙小傑~～">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/1.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="CNSYEAR BLOG'S">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2019/03/24/Springboot多线程并发定时任务/" itemprop="url">Springboot多线程并发定时任务</a></h1>
        

        <div class="post-meta">
		 
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-03-24T16:04:00+08:00">
                2019-03-24
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/SpringBoot/" itemprop="url" rel="index">
                    <span itemprop="name">SpringBoot</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <blockquote>
<p>Springboot多线程并发定时任务</p>
</blockquote>
<p>刚刚看了下Spring Boot实现定时任务的文章，感觉还不错。Spring Boot 使用Spring自带的Schedule来实现定时任务变得非常简单和方便。</p>
<ul>
<li>开启缓存注解</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">@SpringBootApplication</span><br><span class="line">@EnableScheduling //开启定时任务</span><br><span class="line">public class Application &#123;</span><br><span class="line"> </span><br><span class="line">    public static void main(String[] args) &#123;</span><br><span class="line">        SpringApplication.run(Application.class, args);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>编写定时任务</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">@Component</span><br><span class="line">public class ScheduledTasks &#123;</span><br><span class="line"> </span><br><span class="line">    private Logger logger = LoggerFactory.getLogger(ScheduledTasks.class);</span><br><span class="line"> </span><br><span class="line">// cron接受cron表达式，根据cron表达式确定定时规则</span><br><span class="line">   @Scheduled(cron=&quot;0/5 * * * * ? &quot;)   //每5秒执行一次 </span><br><span class="line">    public void testCron() &#123;</span><br><span class="line">       DateFormat sdf = new SimpleDateFormat(&quot;yyyy-MM-dd HH:mm:ss&quot;);  </span><br><span class="line">        logger.info(sdf.format(new Date())+&quot;*********每5秒执行一次&quot;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>存在问题</li>
</ul>
<p>后来发现个问题，通过同时测试几个任务发现，所有的任务都是在同一个线程池中的同一个线程来完成的。在实际开发过程中，我们当然不希望所有的任务都运行在一个线程中。</p>
<ul>
<li>解决方案</li>
</ul>
<p>那么，怎么设计成多线程实现并发呢？在网上看到过这样的解决方案。通过ScheduleConfig配置文件实现SchedulingConfigurer接口，并重写setSchedulerfang方法，我们尝试着配置了一下。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">@Configuration</span><br><span class="line">public class ScheduleConfig implements SchedulingConfigurer &#123;</span><br><span class="line">    @Override</span><br><span class="line">    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) &#123;</span><br><span class="line">        </span><br><span class="line">        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>其他</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">@Scheduled所支持的参数：</span><br><span class="line">1.cron：cron表达式，指定任务在特定时间执行；</span><br><span class="line">2.fixedDelay：表示上一次任务执行完成后多久再次执行，参数类型为long，单位ms；</span><br><span class="line">3.fixedDelayString：与fixedDelay含义一样，只是参数类型变为String；</span><br><span class="line">4.fixedRate：表示按一定的频率执行任务，参数类型为long，单位ms；</span><br><span class="line">5.fixedRateString: 与fixedRate的含义一样，只是将参数类型变为String；</span><br><span class="line">6.initialDelay：表示延迟多久再第一次执行任务，参数类型为long，单位ms；</span><br><span class="line">7.initialDelayString：与initialDelay的含义一样，只是将参数类型变为String；</span><br><span class="line">8.zone：时区，默认为当前时区，一般没有用到。</span><br></pre></td></tr></table></figure>
<p>参考链接：</p>
<ul>
<li><a href="https://blog.csdn.net/IT18911008884/article/details/78520046" target="_blank" rel="noopener">https://blog.csdn.net/IT18911008884/article/details/78520046</a></li>
</ul>

          
        
      
    </div>
    
    
    

	<div>
		
	</div>
	<div>
		
	</div>
    

    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
  </section>

  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/page/3/"><i class="fa fa-angle-left"></i></a><a class="page-number" href="/">1</a><span class="space">&hellip;</span><a class="page-number" href="/page/3/">3</a><span class="page-number current">4</span><a class="page-number" href="/page/5/">5</a><span class="space">&hellip;</span><a class="page-number" href="/page/7/">7</a><a class="extend next" rel="next" href="/page/5/"><i class="fa fa-angle-right"></i></a>
  </nav>



          </div>
          


          

        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      

      <section class="site-overview-wrap sidebar-panel sidebar-panel-active">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/images/1.jpg" alt="趙小傑~～">
            
              <p class="site-author-name" itemprop="name">趙小傑~～</p>
              <p class="site-description motion-element" itemprop="description">I MISS YOU.</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">65</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">33</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">33</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          
            <div class="feed-link motion-element">
              <a href="/atom.xml" rel="alternate">
                <i class="fa fa-rss"></i>
                RSS
              </a>
            </div>
          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/cnsyear" target="_blank" title="GitHub">
                      
                        <i class="fa fa-fw fa-github"></i>GitHub</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="mailto:820382480@qq.com" target="_blank" title="E-Mail">
                      
                        <i class="fa fa-fw fa-envelope"></i>E-Mail</a>
                  </span>
                
            </div>
          

          
          

          
          
            <div class="links-of-blogroll motion-element links-of-blogroll-inline">
              <div class="links-of-blogroll-title">
                <i class="fa  fa-fw fa-link"></i>
                友情链接
              </div>
              <ul class="links-of-blogroll-list">
                
                  <li class="links-of-blogroll-item">
                    <a href="https://linuxtools-rst.readthedocs.io/zh_CN/latest/" title="Linux教程" target="_blank">Linux教程</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://ke.qq.com/" title="腾讯课堂" target="_blank">腾讯课堂</a>
                  </li>
                
              </ul>
            </div>
          

          

        </div>
      </section>

      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<div class="copyright">&copy; <span itemprop="copyrightYear">2019</span>
  <span class="with-love">
    <i class="fa fa-heartbeat"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">趙小傑~～</span>

  
</div>




  <div class="powered-by">
	<i class="fa fa-user-md"></i><span id="busuanzi_container_site_uv">
		  本站访客数:<span id="busuanzi_value_site_uv"></span>
	</span>
  </div>
  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Pisces</a> v5.1.4</div>




<div class="theme-info">
  <div class="powered-by"></div>
  <span class="post-count">博客全站共37.3k字</span>
</div>

<!--51La统计-->
<div style="display:none">
	<script type="text/javascript" src="https://js.users.51.la/19388993.js"></script>
</div>
        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
          <span id="scrollpercent"><span>0</span>%</span>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  

  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  













  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    var isXml = true;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length === 0) {
      search_path = "search.xml";
    } else if (/json$/i.test(search_path)) {
      isXml = false;
    }
    var path = "/" + search_path;
    // monitor main search box;

    var onPopupClose = function (e) {
      $('.popup').hide();
      $('#local-search-input').val('');
      $('.search-result-list').remove();
      $('#no-result').remove();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    }

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.search-popup-overlay').click(onPopupClose);
      $('.popup').toggle();
      var $localSearchInput = $('#local-search-input');
      $localSearchInput.attr("autocapitalize", "none");
      $localSearchInput.attr("autocorrect", "off");
      $localSearchInput.focus();
    }

    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';

      // start loading animation
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay">' +
          '<div id="search-loading-icon">' +
          '<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
          '</div>' +
          '</div>')
        .css('overflow', 'hidden');
      $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');

      $.ajax({
        url: path,
        dataType: isXml ? "xml" : "json",
        async: true,
        success: function(res) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = isXml ? $("entry", res).map(function() {
            return {
              title: $("title", this).text(),
              content: $("content",this).text(),
              url: $("url" , this).text()
            };
          }).get() : res;
          var input = document.getElementById(search_id);
          var resultContent = document.getElementById(content_id);
          var inputEventFunction = function() {
            var searchText = input.value.trim().toLowerCase();
            var keywords = searchText.split(/[\s\-]+/);
            if (keywords.length > 1) {
              keywords.push(searchText);
            }
            var resultItems = [];
            if (searchText.length > 0) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var hitCount = 0;
                var searchTextCount = 0;
                var title = data.title.trim();
                var titleInLowerCase = title.toLowerCase();
                var content = data.content.trim().replace(/<[^>]+>/g,"");
                var contentInLowerCase = content.toLowerCase();
                var articleUrl = decodeURIComponent(data.url);
                var indexOfTitle = [];
                var indexOfContent = [];
                // only match articles with not empty titles
                if(title != '') {
                  keywords.forEach(function(keyword) {
                    function getIndexByWord(word, text, caseSensitive) {
                      var wordLen = word.length;
                      if (wordLen === 0) {
                        return [];
                      }
                      var startPosition = 0, position = [], index = [];
                      if (!caseSensitive) {
                        text = text.toLowerCase();
                        word = word.toLowerCase();
                      }
                      while ((position = text.indexOf(word, startPosition)) > -1) {
                        index.push({position: position, word: word});
                        startPosition = position + wordLen;
                      }
                      return index;
                    }

                    indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
                    indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
                  });
                  if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
                    isMatch = true;
                    hitCount = indexOfTitle.length + indexOfContent.length;
                  }
                }

                // show search results

                if (isMatch) {
                  // sort index by position of keyword

                  [indexOfTitle, indexOfContent].forEach(function (index) {
                    index.sort(function (itemLeft, itemRight) {
                      if (itemRight.position !== itemLeft.position) {
                        return itemRight.position - itemLeft.position;
                      } else {
                        return itemLeft.word.length - itemRight.word.length;
                      }
                    });
                  });

                  // merge hits into slices

                  function mergeIntoSlice(text, start, end, index) {
                    var item = index[index.length - 1];
                    var position = item.position;
                    var word = item.word;
                    var hits = [];
                    var searchTextCountInSlice = 0;
                    while (position + word.length <= end && index.length != 0) {
                      if (word === searchText) {
                        searchTextCountInSlice++;
                      }
                      hits.push({position: position, length: word.length});
                      var wordEnd = position + word.length;

                      // move to next position of hit

                      index.pop();
                      while (index.length != 0) {
                        item = index[index.length - 1];
                        position = item.position;
                        word = item.word;
                        if (wordEnd > position) {
                          index.pop();
                        } else {
                          break;
                        }
                      }
                    }
                    searchTextCount += searchTextCountInSlice;
                    return {
                      hits: hits,
                      start: start,
                      end: end,
                      searchTextCount: searchTextCountInSlice
                    };
                  }

                  var slicesOfTitle = [];
                  if (indexOfTitle.length != 0) {
                    slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
                  }

                  var slicesOfContent = [];
                  while (indexOfContent.length != 0) {
                    var item = indexOfContent[indexOfContent.length - 1];
                    var position = item.position;
                    var word = item.word;
                    // cut out 100 characters
                    var start = position - 20;
                    var end = position + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if (end < position + word.length) {
                      end = position + word.length;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
                  }

                  // sort slices in content by search text's count and hits' count

                  slicesOfContent.sort(function (sliceLeft, sliceRight) {
                    if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
                      return sliceRight.searchTextCount - sliceLeft.searchTextCount;
                    } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
                      return sliceRight.hits.length - sliceLeft.hits.length;
                    } else {
                      return sliceLeft.start - sliceRight.start;
                    }
                  });

                  // select top N slices in content

                  var upperBound = parseInt('1');
                  if (upperBound >= 0) {
                    slicesOfContent = slicesOfContent.slice(0, upperBound);
                  }

                  // highlight title and content

                  function highlightKeyword(text, slice) {
                    var result = '';
                    var prevEnd = slice.start;
                    slice.hits.forEach(function (hit) {
                      result += text.substring(prevEnd, hit.position);
                      var end = hit.position + hit.length;
                      result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
                      prevEnd = end;
                    });
                    result += text.substring(prevEnd, slice.end);
                    return result;
                  }

                  var resultItem = '';

                  if (slicesOfTitle.length != 0) {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
                  } else {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
                  }

                  slicesOfContent.forEach(function (slice) {
                    resultItem += "<a href='" + articleUrl + "'>" +
                      "<p class=\"search-result\">" + highlightKeyword(content, slice) +
                      "...</p>" + "</a>";
                  });

                  resultItem += "</li>";
                  resultItems.push({
                    item: resultItem,
                    searchTextCount: searchTextCount,
                    hitCount: hitCount,
                    id: resultItems.length
                  });
                }
              })
            };
            if (keywords.length === 1 && keywords[0] === "") {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
            } else if (resultItems.length === 0) {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
            } else {
              resultItems.sort(function (resultLeft, resultRight) {
                if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
                  return resultRight.searchTextCount - resultLeft.searchTextCount;
                } else if (resultLeft.hitCount !== resultRight.hitCount) {
                  return resultRight.hitCount - resultLeft.hitCount;
                } else {
                  return resultRight.id - resultLeft.id;
                }
              });
              var searchResultList = '<ul class=\"search-result-list\">';
              resultItems.forEach(function (result) {
                searchResultList += result.item;
              })
              searchResultList += "</ul>";
              resultContent.innerHTML = searchResultList;
            }
          }

          if ('auto' === 'auto') {
            input.addEventListener('input', inputEventFunction);
          } else {
            $('.search-icon').click(inputEventFunction);
            input.addEventListener('keypress', function (event) {
              if (event.keyCode === 13) {
                inputEventFunction();
              }
            });
          }

          // remove loading animation
          $(".local-search-pop-overlay").remove();
          $('body').css('overflow', '');

          proceedsearch();
        }
      });
    }

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched === false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(onPopupClose);
    $('.popup').click(function(e){
      e.stopPropagation();
    });
    $(document).on('keyup', function (event) {
      var shouldDismissSearchPopup = event.which === 27 &&
        $('.search-popup').is(':visible');
      if (shouldDismissSearchPopup) {
        onPopupClose();
      }
    });
  </script>





  

  

  
<script>
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';        
    }
    else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>


  
  

  

  

  

  
  <!-- 页面点击小红心，在末尾添加，避免找不到 -->
  <script type="text/javascript" src="/js/src/love.js"></script>
  <!--看板娘-->
  <script src="/live2d-widget/autoload.js"></script>

</body>
</html>
